#ifndef SDK_DEF_H
#define SDK_DEF_H

#include <functional>
#include <list>
#include <mutex>
#include <string>
#include <memory>

using namespace std;

#define IOT_OK 0

namespace gmtiot
{
    using guard = std::unique_lock<std::mutex>;

    /**
     * @brief cloud state
     */
    enum CloudState
    {
        CloudStateOffline,
        CloudStateOnline
    };

    /**
     * @brief network config steps define
     */
    enum ConfigNetworkStep
    {
        ConfigStepStopped = 0,
        ConfigStepStarting,
        ConfigStepAPConnecting,
        ConfigStepAPConnected,
        ConfigStepBLEConnecting,
        ConfigStepBLEConnected,
        ConfigStepWiFiConnecting,
        ConfigStepWiFiConnected
    };
    /**
     * @brief attribute value 
     */
    typedef struct
    {
        string name;
        string value;
    } AttributeValue;
    /**
     * @brief application version informations
     */
    typedef struct
    {
        string packageName;
        string platform;
        string versionName;
        int versionCode;
    } PackageVersion;
    /**
     * @brief attribute value 
     */
    typedef struct
    {
        string deviceId;
        string modelCode;
        string modelName;
        string typeId;
        string typeName;
        string brandName;
        string productName;

        bool onOffStatus;

    } DeviceInfo;
    /**
     * @brief upgrade file information
     */
    typedef struct
    {
        string fileUrl;
        string fileSize;
        string versionName;
        int versionCode;
        string oldVersionName;
        int oldVersionCode;
        string checkSum;
    } DownLoadFile;
    /**
     * @brief new package version information
     * 
     */
    typedef struct
    {
        string packageName;
        string type;
        string typeId;
        string modelCode;
        string platform;
        bool silentFlag;

        DownLoadFile fullFile;
        DownLoadFile diffFile;
    } NewVersionInfo;

    /**
     * @brief application sdk callbacks
     */
    class app_callback
    {

    public:
        using ptr_t = std::shared_ptr<app_callback>;

        app_callback() = default;
        virtual ~app_callback() {}
        /**
         * app连接云状态变化回调
         *
         * @param state：CloudState.DeviceStateOnline=连云成功, CloudState.DeviceStateOffline=连云失败
         */
        virtual void onCloudStateChanged(CloudState state) = 0;

        /**
         * 用户账号下绑定设备列表更新
         *
         * @param devices：新的绑定设备列表
         */
        virtual void onDeviceListChanged(list<DeviceInfo> &devices) = 0;

        /**
         * 设备连云状态变化
         *
         * @param deviceId：设备ID
         * @param state：        CloudState.DeviceStateOnline=连云成功, CloudState.DeviceStateOffline=连云失败
         */
        virtual void onDeviceCloudStateChanged(const string &deviceId, CloudState state) = 0;

        /**
         * 设备属性值变化
         *
         * @param deviceId：设备ID
         * @param attributes：   设备最新的属性值列表
         */
        virtual void onDeviceAttributeChanged(const string &deviceId, list<AttributeValue> &attributes) = 0;

        /**
         * 订阅设备结果回调
         *
         * @param result：  true=订阅成功，false=订阅失败
         * @param deviceId
         */
        virtual void onSubscribeResult(bool result, const string &deviceId) = 0;
        /**
         * 发布信息结果回调
         *
         * @param result：  true=订阅成功，false=订阅失败
         * @param deviceId
         */
        virtual void onPublishResult(bool result, const string &deviceId) = 0;

        /**
         * login 回调
         *
         * @param result：  true=订阅成功，false=订阅失败
         * @param userToken: 
         */
        virtual void onLoginResult(bool result, const string &userToken, const string &validEndTime) = 0;
        /**
         * bind device 回调
         *
         * @param result：  true=订阅成功，false=订阅失败
         * @param userToken: 
         */
        virtual void onBindDeviceResult(bool result, const DeviceInfo &deviceInfo) = 0;
    };
    using app_callback_ptr = app_callback::ptr_t;

    /**
     * @brief device sdk callbacks
     */
    class dev_callback
    {
    public:
        using ptr_t = std::shared_ptr<dev_callback>;

        dev_callback() = default;
        virtual ~dev_callback() {}
        /**
         * 设备连云状态变化回调
         *
         * @param state：    DeviceCloudState.DeviceStateOnline=连云成功，DeviceCloudState.DeviceStateOffline=连云失败
         */
        virtual void onDeviceCloudStateChanged(CloudState state) = 0;

        /**
         * 读取设备参数回调，设备需要在Read回调里面读取最新参数并调用response回复Read结果
         *
         * @param attributes： 属性名字列表
         * @param msgId：      消息ID，用于操作同步
         */
        virtual void onDeviceRead(list<AttributeValue> &attributes, const string &msgId) = 0;

        /**
         * 写入设备参数回调，设备需要在Write回调里面写入最新参数并调用response回复Write结果
         *
         * @param attributeValues： 属性键值对
         * @param msgId：      消息ID，用于操作同步
         */
        virtual void onDeviceWrite(list<AttributeValue> &attributeValues, const string &msgId) = 0;

        /**
         * 设备升级回调
         *
         * @param newVersions 升级包信息
         */
        virtual void onNewVersion(list<NewVersionInfo> &newVersions) = 0;
    };
    using dev_callback_ptr = dev_callback::ptr_t;

    /**
     * @brief network config callback
     */
    class config_callback
    {

    public:
        using ptr_t = std::shared_ptr<config_callback>;

        config_callback() = default;
        virtual ~config_callback() {}

        /**
         * @brief 配网进程回调
         * @param step 步骤信息，参考ConfigNetworkStep枚举
         */
        virtual void onConfigProcess(ConfigNetworkStep step) = 0;

        /**
         * @brief 配置AP模式回调，开发者在这个回调中切换WiFi到AP模式
         * 
         * @param apname ap name
         */
        virtual bool onConfigAP(const string &apname) = 0;

        /**
         * @brief 配置Station模式回调，开发者在这个回调中切换WiFi到Station模式
         * 
         * @param ssid WiFi ssid 
         * @param pwd WiFi password
         * @param bssid WiFi bssid
         */
        virtual bool onConfigSTA(const string &ssid, const string &pwd, const string &bssid) = 0;

        /**
         * @brief 配置蓝牙回调，开发者在这个回调中设置设备进去广播模式
         * 
         * @param broadcastName BLE设备广播设备地址
         */
        virtual bool onConfigBLE(const string &broadcastName) = 0;
    };
    using config_callback_ptr = config_callback::ptr_t;
}

#endif // SDK_DEF_H
